package com.pronosticnews.client.admin.activity;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.activity.shared.AbstractActivity;
import com.google.gwt.core.shared.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.place.shared.PlaceController;
import com.google.gwt.user.cellview.client.ColumnSortList;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AcceptsOneWidget;
import com.google.gwt.view.client.AsyncDataProvider;
import com.google.gwt.view.client.HasData;
import com.google.gwt.view.client.SelectionChangeEvent;
import com.google.gwt.view.client.SelectionChangeEvent.Handler;
import com.google.gwt.view.client.SingleSelectionModel;
import com.pronosticnews.client.admin.ClientFactory;
import com.pronosticnews.client.admin.view.listJoueur.ListJoueurView;
import com.pronosticnews.client.admin.view.listJoueur.ListJoueurView.Presenter;
import com.pronosticnews.client.event.DeletedJoueurEvent;
import com.pronosticnews.client.event.InformationMessageEvent;
import com.pronosticnews.client.event.NouveauJoueurEvent;
import com.pronosticnews.client.event.NouveauJoueurEventHandler;
import com.pronosticnews.client.event.SelectedJoueurEvent;
import com.pronosticnews.client.services.JoueurService;
import com.pronosticnews.client.services.JoueurServiceAsync;
import com.pronosticnews.client.util.InformationMessage;
import com.pronosticnews.client.util.InformationMessage.TYPE_MESSAGE;
import com.pronosticnews.shared.model.JoueurDto;

import fr.ysa.services.config.ConfigRequetesDto;
import fr.ysa.services.config.FiltreDto;
import fr.ysa.services.config.TrieDto;
import fr.ysa.services.config.ValueFiltreDto;

public class ListJoueurActivity extends AbstractActivity implements Presenter {

	private ListJoueurView view;
	private JoueurServiceAsync joueurService;

	private AsyncCallback<List<JoueurDto>> getListcallback;
	private AsyncCallback<Integer> rowCountCallback;

	private ConfigRequetesDto configRequetes;

	private PlaceController placeController;
	private SingleSelectionModel<JoueurDto> selectionModel;
	private com.google.web.bindery.event.shared.EventBus eventBus;

	public ListJoueurActivity(ClientFactory clientFactory) {
		eventBus = clientFactory.getEventBus();
		configRequetes = new ConfigRequetesDto();
		view = clientFactory.getListJoueurView();
		placeController = clientFactory.getPlaceController();
		joueurService = GWT.create(JoueurService.class);

		NouveauJoueurEventHandler nouveauJoueurEventHandler = new NouveauJoueurEventHandler() {

			@Override
			public void onCreate(NouveauJoueurEvent event) {
				getListJoueur(configRequetes, getListcallback);
			}
		};
		clientFactory.getEventBus().addHandler(NouveauJoueurEvent.TYPE,
				nouveauJoueurEventHandler);
	}

	@Override
	public void start(AcceptsOneWidget container, EventBus eventBus) {
		view.setPresenter(this);
		getJoueurRowCount(new ConfigRequetesDto());
		initAsyncProvider();
		container.setWidget(view.asWidget());
	}

	private void getJoueurRowCount(ConfigRequetesDto config) {
		if (rowCountCallback == null) {
			rowCountCallback = new AsyncCallback<Integer>() {

				@Override
				public void onSuccess(Integer result) {
					view.setRowCount(result);
				}

				@Override
				public void onFailure(Throwable caught) {
					InformationMessage erreur = new InformationMessage();
					List<String> messages = new ArrayList<String>();
					messages.add(caught.getMessage());
					erreur.setText(messages);
					erreur.setType(TYPE_MESSAGE.ERROR);
					// eventBus.fireEvent(new InformationMessageEvent(erreur));
				}
			};
		}
		joueurService.compter(config, rowCountCallback);
	}

	public void getListJoueur(ConfigRequetesDto config,
			AsyncCallback<List<JoueurDto>> callback) {
		getJoueurRowCount(config);
		joueurService.trouver(config, callback);
	}

	private void initAsyncProvider() {

		getListcallback = new AsyncCallback<List<JoueurDto>>() {

			@Override
			public void onSuccess(List<JoueurDto> result) {
				view.setJoueur(configRequetes.getDebut(), result);
			}

			@Override
			public void onFailure(Throwable caught) {
				InformationMessage erreur = new InformationMessage();
				List<String> messages = new ArrayList<String>();
				messages.add(caught.getMessage());
				erreur.setText(messages);
				erreur.setType(TYPE_MESSAGE.ERROR);
				eventBus.fireEvent(new InformationMessageEvent(erreur));
			}
		};

		selectionModel = new SingleSelectionModel<JoueurDto>();
		Handler selectionChangeHandler = new Handler() {

			@Override
			public void onSelectionChange(SelectionChangeEvent event) {
				eventBus.fireEvent(new SelectedJoueurEvent(selectionModel
						.getSelectedObject()));
			}
		};
		selectionModel.addSelectionChangeHandler(selectionChangeHandler);

		view.getHasData().setSelectionModel(selectionModel);

		AsyncDataProvider<JoueurDto> provider = new AsyncDataProvider<JoueurDto>() {

			@Override
			protected void onRangeChanged(HasData<JoueurDto> display) {

				final int start = display.getVisibleRange().getStart();
				int length = display.getVisibleRange().getLength();

				ColumnSortList sortList = view.getColumnSortList();
				if (sortList.size() > 0) {
					TrieDto trie = getTrie(sortList.get(0).getColumn()
							.getDataStoreName());
					if (trie == null) {
						trie = new TrieDto();
						trie.setChamp(sortList.get(0).getColumn()
								.getDataStoreName());
						configRequetes.getTries().add(trie);
					}
					trie.setOrdre(sortList.get(0).isAscending());
				}

				configRequetes.setDebut(start);
				configRequetes.setNombre(length);
				getListJoueur(configRequetes, getListcallback);
			}
		};
		provider.addDataDisplay(view.getHasData());
	}

	private TrieDto getTrie(String column) {
		int indTrie = 0;
		while (indTrie < configRequetes.getTries().size()
				&& !column.equals(configRequetes.getTries().get(indTrie)
						.getChamp())) {
			indTrie++;
		}
		if (indTrie < configRequetes.getTries().size()) {
			return configRequetes.getTries().get(indTrie);
		} else {
			return null;
		}
	}

	private FiltreDto getFiltre(String column) {
		int indFiltre = 0;
		while (indFiltre < configRequetes.getFiltres().size()
				&& !column.equals(configRequetes.getFiltres().get(indFiltre)
						.getName())) {
			indFiltre++;
		}
		if (indFiltre < configRequetes.getFiltres().size()) {
			return configRequetes.getFiltres().get(indFiltre);
		} else {
			return null;
		}
	}

	@Override
	public void updateFiltreRequete(List<FiltreDto> filtres) {
		boolean filtrer = true;
		if (filtres == null) {
			if (configRequetes.getFiltres().size() == 0) {
				filtrer = false;
			} else {
				configRequetes.getFiltres().clear();
			}
		} else {
			for (FiltreDto filtreDto : filtres) {
				FiltreDto filtre = getFiltre(filtreDto.getName());
				if (filtre != null) {
					ValueFiltreDto valueFiltreDto = new ValueFiltreDto();
					valueFiltreDto.setValue(filtreDto.getValues().get(0)
							.getValue());
					valueFiltreDto.setOperation(filtreDto.getValues().get(0)
							.getOperation());

					filtre.getValues().clear();
					filtre.addValue(valueFiltreDto);
				} else {
					filtre = new FiltreDto();
					filtre.setName(filtreDto.getName());
					filtre.setType(filtreDto.getType());
					ValueFiltreDto valueFiltreDto = new ValueFiltreDto();
					valueFiltreDto.setValue(filtreDto.getValues().get(0)
							.getValue());
					valueFiltreDto.setOperation(filtreDto.getValues().get(0)
							.getOperation());
					filtre.addValue(valueFiltreDto);
					configRequetes.getFiltres().add(filtre);
				}
			}
		}
		if (filtrer) {
			getListJoueur(configRequetes, getListcallback);
		}
	}

	@Override
	public void supprimeSelected() {
		if (selectionModel != null
				&& selectionModel.getSelectedObject() != null) {
			AsyncCallback<Void> supprimeCallback = new AsyncCallback<Void>() {

				@Override
				public void onSuccess(Void result) {
					InformationMessage messageSuccess = new InformationMessage();
					messageSuccess.setType(TYPE_MESSAGE.SUCCESS);
					List<String> messages = new ArrayList<String>();
					messages.add("Joueur supprimé avec succès");
					messageSuccess.setText(messages);
					getListJoueur(configRequetes, getListcallback);
					eventBus.fireEvent(new DeletedJoueurEvent());
					eventBus.fireEvent(new InformationMessageEvent(
							messageSuccess));
				}

				@Override
				public void onFailure(Throwable caught) {
					InformationMessage messageError = new InformationMessage();
					messageError.setType(TYPE_MESSAGE.ERROR);
					List<String> messages = new ArrayList<String>();
					messages.add(caught.getMessage());
					messageError.setText(messages);
					eventBus.fireEvent(new InformationMessageEvent(messageError));
				}
			};
			joueurService.supprimer(selectionModel.getSelectedObject(),
					supprimeCallback);
		}
	}
}
